package cn.microservices.cloud.gateway.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

public class WebFluxUtil {
    private static final String EMPTY = "";

	private Logger log = LoggerFactory.getLogger(getClass());

    public static String getRealIp(ServerHttpRequest request) {
        String ipAddress = "";
        try {
            if (request == null) {
                return ipAddress;
            }
            HttpHeaders headers = request.getHeaders();
            //阿里云代理的先获取
            ipAddress = headers.getFirst("X-Forwarded-For");
            if (!StringUtils.isEmpty(ipAddress)) {
                //获取第一个IP
                if (ipAddress.contains(",")) {
                    for (String ip_add : ipAddress.split(",")) {
                        ipAddress = ip_add;
                        if (!StringUtils.isEmpty(ipAddress)) {
                            break;
                        }
                    }
                }
                return ipAddress;
            }


            ipAddress = headers.getFirst("x-forwarded-for");
            if (StringUtils.isEmpty(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = headers.getFirst("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = headers.getFirst("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddress().getAddress().getHostAddress();
            }
            if (StringUtils.isEmpty(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = headers.getFirst("X-Real-IP");
            }
            if (ipAddress != null && ipAddress.contains("0:0:0:0:0:0:0:1")) {
                // 根据网卡取本机配置的IP

                // linux下也可以获取本地的ip地址
                Enumeration<?> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
                InetAddress ip;
                while (allNetInterfaces.hasMoreElements()) {
                    NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                    Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        ip = addresses.nextElement();
                        if (ip != null && ip instanceof Inet4Address) {
                            // 获取真实的Ip地址
                            ipAddress = ip.getHostAddress();

                        }
                    }
                }

            }

            // 多个路由时，取第一个非unknown的ip
            final String[] arr = ipAddress.split(",");
            for (final String str : arr) {
                if (!"unknown".equalsIgnoreCase(str)) {
                    ipAddress = str;
                    break;
                }
            }


        } catch (Exception e) {

        }


        return ipAddress;
    }

    /**
     * 返回特定的结果
     *
     * @param response 返回的response
     * @return
     */
    public static Mono<Void> echo(ServerHttpResponse response) {
        return echo(response, EMPTY);
    }

    /**
     * 返回特定的结果
     *
     * @param response 返回的response
     * @param echo     需要返回的字符串
     * @return
     */
    public static Mono<Void> echo(ServerHttpResponse response, String echo) {
        return response.writeWith(Flux.just(response.bufferFactory().wrap(echo.getBytes())));
    }
    /**
     * 返回特定的结果
     *
     * @param response 返回的response
     * @return
     */
    public static Mono<Void> err(String msg) {
        throw new RuntimeException(msg);
    }


}
